package com.ziiwee.reduce.rest.condition.parser;

import com.ziiwee.reduce.rest.condition.Condition;
import com.ziiwee.reduce.rest.condition.Conditions;
import org.json.JSONArray;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

/**
 * @author ziiwee
 * @since 2021/3/12
 */
public class JsonConditionParser extends AbstractConditionParser {

    public final static String OP = "op";
    public final static String FIELD = "field";
    public final static String VALUE = "value";
    public final static String VALUES = "values";
    public final static String VALUE1 = "value1";
    public final static String VALUE2 = "value2";


    public JsonConditionParser(Class<?> modelType) {
        super(modelType);
    }

    @Override
    public Condition parse(String s) {
        try {
            return parseJson(new JSONObject(s));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public Condition parseJson(JSONObject json) {
        String op = json.getString(OP);
        switch (op) {
            case "and":
                return and(json);
            case "or":
                return or(json);
            case "like":
                return like(json);
            case "in":
                return in(json);
            case "notIn":
                return notIn(json);
            case "isNull":
                return isNull(json);
            case "isNotNull":
                return isNotNull(json);
            case "eq":
                return eq(json);
            case "ne":
                return ne(json);
            case "gt":
                return gt(json);
            case "gte":
                return gte(json);
            case "lt":
                return lt(json);
            case "lte":
                return lte(json);
            case "between":
                return between(json);
        }
        return null;
    }

    public List<Condition> parseJsonArray(JSONArray array) {
        List<Condition> conditions = new ArrayList<>();
        for (int i = 0; i < array.length(); i++) {
            JSONObject it = array.getJSONObject(i);
            if (it != null) {
                conditions.add(parseJson(it));
            }
        }
        return conditions;
    }

    public Condition and(JSONObject json) {
        return Conditions.and(parseJsonArray(json.getJSONArray(VALUES)));
    }

    public Condition or(JSONObject json) {
        return Conditions.or(parseJsonArray(json.getJSONArray(VALUES)));
    }

    public Condition like(JSONObject json) {
        String value = json.getString(VALUE);
//        if (!value.contains("%")) {
//            value = "%" + value + "%";
//        }
        return Conditions.like(json.getString(FIELD), value);
    }

    public Condition in(JSONObject json) {
        String field = json.getString(FIELD);
        List<Object> values = new ArrayList<>();
        JSONArray array = json.getJSONArray(VALUES);
        for (int i = 0; i < array.length(); i++) {
            String value = array.getString(i);
            values.add(castValue(field, value));
        }
        return Conditions.in(field, values);
    }
    public Condition notIn(JSONObject json) {
        String field = json.getString(FIELD);
        List<Object> values = new ArrayList<>();
        JSONArray array = json.getJSONArray(VALUES);
        for (int i = 0; i < array.length(); i++) {
            String value = array.getString(i);
            values.add(castValue(field, value));
        }
        return Conditions.notIn(field, values);
    }

    public Condition isNull(JSONObject json) {
        return Conditions.isNull(json.getString(FIELD));
    }

    public Condition isNotNull(JSONObject json) {
        return Conditions.isNotNull(json.getString(FIELD));
    }

    public Condition eq(JSONObject json) {
        String field = json.getString(FIELD);
        String value = json.get(VALUE).toString();
        return Conditions.eq(field, castValue(field, value));
    }

    public Condition ne(JSONObject json) {
        String field = json.getString(FIELD);
        String value = json.get(VALUE).toString();
        return Conditions.ne(field, castValue(field, value));
    }

    @SuppressWarnings("unchecked")
    public Condition gt(JSONObject json) {
        String field = json.getString(FIELD);
        String value = json.getString(VALUE);
        return Conditions.gt(field, castComparable(field, value));
    }

    @SuppressWarnings("unchecked")
    public Condition gte(JSONObject json) {
        String field = json.getString(FIELD);
        String value = json.getString(VALUE);
        return Conditions.gte(field, castComparable(field, value));
    }

    @SuppressWarnings("unchecked")
    public Condition lt(JSONObject json) {
        String field = json.getString(FIELD);
        String value = json.getString(VALUE);
        return Conditions.lt(field, castComparable(field, value));
    }

    @SuppressWarnings("unchecked")
    public Condition lte(JSONObject json) {
        String field = json.getString(FIELD);
        String value = json.getString(VALUE);
        return Conditions.lte(field, castComparable(field, value));
    }

    @SuppressWarnings("unchecked")
    public Condition between(JSONObject json) {
        String field = json.getString(FIELD);
        String value1 = json.getString(VALUE1);
        String value2 = json.getString(VALUE2);
        return Conditions.between(field, castComparable(field, value1), castComparable(field, value2));
    }
}
